# -*- sh -*-
#
# test container-related endpoints
#

# WORKDIR=/data
MultiTagName=localhost/test/testformultitag:tag

podman pull $IMAGE &>/dev/null
podman tag $IMAGE $MultiTagName
# Unimplemented
#t POST libpod/containers/create '' 201 'sdf'

# Ensure clean slate
podman rm -a -f &>/dev/null

t GET "libpod/containers/json (at start: clean slate)" 200 \
  "[]" \
  length=0
# check content type: https://github.com/containers/podman/issues/14647
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/json.*" "header does not contain application/json"

# Regression test for #12904 (race condition in logging code)
mytext="hi-there-$(random_string 15)"
podman run --rm -d --replace --name foo $IMAGE sh -c "echo $mytext;sleep 42"
# Logs output is prepended by ^A^Y (stdout = 1, length = 25 (with newline))
# Looks like it is missing the required 0 bytes from the message, why?
t POST "containers/foo/attach?logs=true&stream=false" 200 \
  $'\001\031'$mytext

# check old docker header
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "vnd.docker.raw-stream docker v1.40"
# check new vnd.docker.multiplexed-stream header
t POST "/v1.42/containers/foo/attach?logs=true&stream=false" 200
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/vnd\.docker\.multiplexed-stream.*" "vnd.docker.multiplexed-stream docker v1.42"
t POST "/v4.6.0/libpod/containers/foo/attach?logs=true&stream=false" 200
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "vnd.docker.raw-stream libpod v4.6.0"
t POST "/v4.7.0/libpod/containers/foo/attach?logs=true&stream=false" 200
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/vnd\.docker\.multiplexed-stream.*" "vnd.docker.multiplexed-stream libpod v4.7.0"

t POST "containers/foo/attach?logs=true&stream=false" 101
response_headers=$(cat "$WORKDIR/curl.headers.out")
like "$response_headers" ".*Content-Type: application/vnd\.docker\.raw-stream.*" "hijacked connection header: Content-type: application/vnd.docker.raw-stream"
like "$response_headers" ".*Upgrade: tcp.*" "hijacked connection header: Upgrade: tcp"

t POST "containers/foo/kill" 204

podman run --replace --name=foo -v /tmp:/tmp $IMAGE true
# cannot kill non-running container
t POST "containers/foo/kill" 409
t POST "libpod/containers/foo/kill" 409

t GET libpod/containers/json 200 length=0

# bad all input
t GET libpod/containers/json?all='garb1age' 500 \
    .cause="schema: error converting value for \"all\""

t GET libpod/containers/json?all=true 200 \
  length=1 \
  .[0].Id~[0-9a-f]\\{64\\} \
  .[0].Image=$IMAGE \
  .[0].Command[0]="true" \
  .[0].State~\\\(exited\\\|stopped\\\) \
  .[0].ExitCode=0 \
  .[0].Mounts~.*/tmp \
  .[0].IsInfra=false

# Test compat API for Network Settings (.Network is N/A when rootless)
network_expect="Networks.pasta.NetworkID=pasta"
if root; then
    network_expect="Networks.podman.NetworkID=podman"
fi
t GET /containers/json?all=true 200 \
  length=1 \
  .[0].Id~[0-9a-f]\\{64\\} \
  .[0].Image=$IMAGE \
  .[0].Mounts~.*/tmp \
  .[0].NetworkSettings.$network_expect

# compat API imageid with sha256: prefix
t GET containers/json?limit=1 200 \
  .[0].ImageID~sha256:[0-9a-f]\\{64\\}

# Make sure `limit` works.
t GET libpod/containers/json?limit=1 200 \
  length=1 \
  .[0].Id~[0-9a-f]\\{64\\} \
  .[0].Image=$IMAGE \
  .[0].Command[0]="true" \
  .[0].State~\\\(exited\\\|stopped\\\) \
  .[0].ExitCode=0 \
  .[0].IsInfra=false

# Make sure `last` works, which is an alias for `limit`.
# See https://github.com/containers/podman/issues/6413.
t GET libpod/containers/json?last=1 200 \
  length=1 \
  .[0].Id~[0-9a-f]\\{64\\} \
  .[0].Image=$IMAGE \
  .[0].Command[0]="true" \
  .[0].State~\\\(exited\\\|stopped\\\) \
  .[0].ExitCode=0 \
  .[0].IsInfra=false

cid=$(jq -r '.[0].Id' <<<"$output")

t GET "libpod/containers/stats?containers=$cid&stream=false" 200 \
  .memory_stats.max_usage=null

t DELETE libpod/containers/$cid 200 .[0].Id=$cid

# Issue #14676: make sure the stats show the memory limit specified for the container
if root; then
    CTRNAME=ctr-with-limit
    podman run --name $CTRNAME -d -m 512m -v /tmp:/tmp $IMAGE top

    t GET libpod/containers/$CTRNAME/stats?stream=false 200 \
    .memory_stats.limit=536870912 \
    .Id~[0-9a-f]\\{64\\}

    # Make sure docker compat endpoint shows "id" lowercase
    t GET containers/$CTRNAME/stats?stream=false 200 \
    .memory_stats.limit=536870912 \
    .id~[0-9a-f]\\{64\\}

    t GET containers/$CTRNAME/top?stream=false 200 \
      .Titles='[
  "UID",
  "PID",
  "PPID",
  "C",
  "STIME",
  "TTY",
  "TIME",
  "CMD"
]'

    podman rm -f $CTRNAME
fi

# Verify that compat top endpoint combines multi-entry COMMAND lines
CTRNAME=testtopproc
podman run --name $CTRNAME -d $IMAGE sleep 25
t GET containers/$CTRNAME/top?stream=false 200 \
  .Processes.[0].[6]="00:00:00" \
  .Processes.[0].[7]="sleep 25"
podman rm -f -t0 $CTRNAME

CTRNAME=test123
podman run --name $CTRNAME -d $IMAGE top
t GET libpod/containers/$CTRNAME/top?ps_args=--invalid 500 \
  .cause~".*unknown gnu long option.*"
t GET containers/$CTRNAME/top?ps_args=--invalid 500 \
  .cause~".*unknown gnu long option.*"

podman rm -f $CTRNAME

# Issue #15765: make sure the memory limit is capped
if root; then
    CTRNAME=ctr-with-limit
    podman run --name $CTRNAME -d -m 512m -v /tmp:/tmp $IMAGE top

    t GET libpod/containers/$CTRNAME/stats?stream=false 200 \
    .memory_stats.limit!=18446744073709552000

    podman rm -f $CTRNAME
fi

# Container create without existing image should return 404
t POST libpod/containers/create Image="foo" 404 \
  .cause="image not known"

# Issue #6799: it should be possible to start a container, even w/o args.
t POST libpod/containers/create?name=test_noargs Image=${IMAGE} 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
# Prior to the fix in #6835, this would fail 500 "args must not be empty"
t POST   libpod/containers/${cid}/start 204
# Container should exit almost immediately. Wait for it, confirm successful run
t POST   "libpod/containers/${cid}/wait?condition=stopped&condition=exited"  200 '0'
t GET    libpod/containers/${cid}/json 200 \
  .Id=$cid \
  .State.Status~\\\(exited\\\|stopped\\\) \
  .State.Running=false \
  .State.ExitCode=0 \
  .Config.Umask=0022 # regression check for #15036
t DELETE libpod/containers/$cid 200 .[0].Id=$cid

CNAME=myfoo
podman run -d --name $CNAME $IMAGE top
t GET libpod/containers/json?all=true 200 \
  .[0].Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.[0].Id' <<<"$output")

# No such container
t POST "libpod/commit?container=nonesuch" 404

# Comment can only be used with docker format, not OCI
cparam="repo=newrepo&comment=foo&author=bob"
t POST "libpod/commit?container=$CNAME&$cparam"  500 \
  .cause="messages are only compatible with the docker image format (-f docker)"

# Commit a new image from the container
t POST "libpod/commit?container=$CNAME" 200 \
  .Id~[0-9a-f]\\{64\\}
iid=$(jq -r '.Id' <<<"$output")
t GET libpod/images/$iid/json 200 \
  .RepoTags[0]=null \
  .Author="" \
  .Comment=""

# Commit a new image w/o tag
cparam="repo=newrepo&comment=foo&author=bob&format=docker"
t POST "libpod/commit?container=$CNAME&$cparam" 200
t GET libpod/images/newrepo:latest/json 200 \
  .RepoTags[0]=localhost/newrepo:latest	\
  .Author=bob \
  .Comment=foo

# Commit a new image w/ specified tag and author
cparam="repo=newrepo&tag=v1&author=alice"
t POST "libpod/commit?container=$cid&$cparam&pause=false" 200
t GET libpod/images/newrepo:v1/json 200 \
  .RepoTags[0]=localhost/newrepo:v1     \
  .Author=alice

# Commit a new image w/ full parameters
cparam="repo=newrepo&tag=v2&comment=bar&author=eric"
cparam="$cparam&format=docker&changes=CMD=/bin/foo"

t POST "libpod/commit?container=${cid:0:12}&$cparam&pause=true" 200
t GET libpod/images/newrepo:v2/json 200 \
  .RepoTags[0]=localhost/newrepo:v2	\
  .Author=eric \
  .Comment=bar \
  .Config.Cmd[-1]="/bin/foo"
t DELETE images/localhost/newrepo:v2?force=true 200

# Create a container for testing the container initializing later
podman create -t -i --name myctr $IMAGE ls

# Check configuration before initializing
t GET libpod/containers/myctr/json 200 \
  .Id~[0-9a-f]\\{64\\} \
  .State.Status="created" \
  .State.Pid=0 \
  .ResolvConfPath="" \
  .HostnamePath="" \
  .HostsPath="" \
  .NetworkSettings.SandboxKey=""

cpid_file=$(jq -r '.ConmonPidFile' <<<"$output")
userdata_path=$(dirname $cpid_file)

# Initializing the container
t POST libpod/containers/myctr/init 204

# Check configuration after initializing
t GET libpod/containers/myctr/json 200 \
  .Id~[0-9a-f]\\{64\\} \
  .State.Status="initialized" \
  .State.Pid~[0-9]\\{1\,8\\} \
  .ResolvConfPath=$userdata_path/resolv.conf \
  .HostnamePath=$userdata_path/hostname \
  .HostsPath=$userdata_path/hosts \
  .NetworkSettings.SandboxKey~.*/netns/netns- \
  .OCIConfigPath~.*config\.json \
  .GraphDriver.Data.MergedDir~.*merged

# Test TS are in UTC
t GET containers/myctr/json 200 \
  .Created~.*Z \
  .State.StartedAt~.*Z \
  .State.FinishedAt~.*Z

t DELETE images/localhost/newrepo:latest?force=true 200
t DELETE images/localhost/newrepo:v1?force=true 200
t DELETE libpod/containers/$cid?force=true 200 .[0].Id=$cid
t DELETE libpod/containers/myctr 200
t DELETE libpod/containers/bogus 404


# test apiv2 create container with correct entrypoint and cmd
# --data '{"Image":"quay.io/libpod/some:thing","Entrypoint":["echo"],"Cmd":["param1","param2"]}'
t POST containers/create \
  Image=$IMAGE \
  Entrypoint='["echo"]' \
  Cmd='["param1","param2"]' \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Config.Entrypoint[0]="echo" \
  .Config.Cmd[0]="param1" \
  .Config.Cmd[1]="param2" \
  .Path="echo" \
  .Args[0]="param1" \
  .Args[1]="param2"
t DELETE containers/$cid 204

# test only set the entrypoint, Cmd should be []
t POST containers/create \
  Image=$IMAGE \
  Entrypoint='["echo","param1"]' \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Config.Entrypoint[0]="echo" \
  .Config.Entrypoint[1]="param1" \
  .Config.Cmd='[]' \
  .Path="echo" \
  .Args[0]="param1"

# create a running container for after
t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \
  .Id~[0-9a-f]\\{64\\}
cid_top=$(jq -r '.Id' <<<"$output")

t GET containers/${cid_top}/json 200 \
  .Config.Entrypoint[0]="top" \
  .Config.Cmd='[]' \
  .Config.StopTimeout="10" \
  .Path="top" \
  .NetworkSettings.Networks.podman.NetworkID=podman
t POST  containers/${cid_top}/start 204
# make sure the container is running
t GET containers/${cid_top}/json 200 \
  .State.Status="running"

# 0 means unlimited, need same with docker
t GET containers/json?limit=0 200 \
  .[0].Id~[0-9a-f]\\{64\\}

t GET 'containers/json?limit=0&all=1' 200 \
  .[0].Id~[0-9a-f]\\{64\\} \
  .[1].Id~[0-9a-f]\\{64\\}

t GET containers/json?limit=2 200 length=2

# Filter with two ids should return both container
t GET containers/json?filters='{"id":["'${cid}'","'${cid_top}'"]}&all=1' 200 length=2
# Filter with two ids and status running should return only 1 container
t GET containers/json?filters='{"id":["'${cid}'","'${cid_top}'"],"status":["running"]}&all=1' 200 \
  length=1 \
  .[0].Id=${cid_top}

t POST containers/${cid_top}/stop 204

t DELETE containers/$cid 204
t DELETE containers/$cid_top 204

# test the WORKDIR and StopSignal
t POST containers/create \
  Image=$IMAGE \
  WorkingDir=/dataDir \
  StopSignal=\"9\" \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Config.WorkingDir="/dataDir" \
  .Config.StopSignal="9"

t DELETE containers/$cid 204

# when the image had multi tags, the container's Image should be correct
# Fixes https://github.com/containers/podman/issues/8547
t POST containers/create Image=${MultiTagName} 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Config.Image=${MultiTagName} \
  .Image~sha256:[0-9a-f]\\{64\\}

t DELETE containers/$cid 204
t DELETE images/${MultiTagName} 200
# vim: filetype=sh

# Test Volumes field adds an anonymous volume
t POST containers/create Image=$IMAGE Volumes='{"/test":{}}' 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Mounts[0].Destination="/test"

t DELETE containers/$cid?v=true 204

# Test Volumes with bind mount, for some reason docker-py sets this #18454
t POST containers/create Image=$IMAGE Volumes='{"/test/":{}}'  HostConfig='{"Binds":["/tmp:/test/:ro"]}'  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Mounts[0].Destination="/test/"

t DELETE containers/$cid?v=true 204

# test port mapping
podman run -d --rm --name bar -p 8080:9090 $IMAGE top

t GET containers/json 200 \
  .[0].Ports[0].PrivatePort=9090 \
  .[0].Ports[0].PublicPort=8080 \
  .[0].Ports[0].Type="tcp"

podman stop bar

#compat api list containers sanity checks
podman run -d --rm --name labelcontainer_with --label slartibart=fast $IMAGE top
podman run -d --rm --name labelcontainer_without $IMAGE top

t GET containers/json?filters='garb1age}' 500 \
    .cause="invalid character 'g' looking for beginning of value"
t GET containers/json?filters='{"label":["testl' 500 \
    .cause="unexpected end of JSON input"


#libpod api list containers sanity checks
t GET libpod/containers/json?filters='{"status":["removing"]}' 200 length=0
t GET libpod/containers/json?filters='{"status":["bogus"]}' 500 \
    .cause="invalid argument"
t GET libpod/containers/json?filters='garb1age}' 500 \
    .cause="invalid character 'g' looking for beginning of value"
t GET libpod/containers/json?filters='{"label":["testl' 500 \
    .cause="unexpected end of JSON input"

# Prune containers - bad filter input
t POST containers/prune?filters='garb1age}' 500 \
    .cause="invalid character 'g' looking for beginning of value"
t POST libpod/containers/prune?filters='garb1age}' 500 \
    .cause="invalid character 'g' looking for beginning of value"

# Prune containers with illformed label
t POST containers/prune?filters='{"label":["tes' 500 \
    .cause="unexpected end of JSON input"
t POST libpod/containers/prune?filters='{"label":["tes' 500 \
    .cause="unexpected end of JSON input"

t GET libpod/containers/json?filters='{"label":["slartibart"]}' 200 \
  length=1 \
  .[0].Names[0]="labelcontainer_with"
t GET libpod/containers/json?filters='{"label!":["slartibart"]}' 200 \
  length=1 \
  .[0].Names[0]="labelcontainer_without"
t GET libpod/containers/json?filters='{"label!":["testlabel"]}' 200 length=2

podman stop -t0 labelcontainer_with labelcontainer_without

# libpod api: do not use list filters for prune
t POST libpod/containers/prune?filters='{"name":["anyname"]}' 500 \
    .cause="name is an invalid filter"
t POST libpod/containers/prune?filters='{"id":["anyid"]}' 500 \
    .cause="id is an invalid filter"
t POST libpod/containers/prune?filters='{"network":["anynetwork"]}' 500 \
    .cause="network is an invalid filter"

# compat api: do not use list filters for prune
t POST containers/prune?filters='{"name":["anyname"]}' 500 \
    .cause="name is an invalid filter"
t POST containers/prune?filters='{"id":["anyid"]}' 500 \
    .cause="id is an invalid filter"
t POST containers/prune?filters='{"network":["anynetwork"]}' 500 \
    .cause="network is an invalid filter"

# Test CPU limit (NanoCPUs)
nanoCpu=500000
t POST containers/create Image=$IMAGE HostConfig='{"NanoCpus":500000}' 201 \
  .Id~[0-9a-f]\\{64\\}

cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .HostConfig.NanoCpus=$nanoCpu

t DELETE containers/$cid?v=true 204

# Test Compat Create with default network mode (#10569)
t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .HostConfig.NetworkMode="bridge"

t DELETE containers/$cid?v=true 204

# test create with default netns="host"
stop_service
CONTAINERS_CONF=$TESTS_DIR/containers.host-netns.conf start_service

# check that the default docker netns "default" is rewritten to "host"
# when the containers.conf explicitly uses "host"
t POST containers/create Image=$IMAGE HostConfig='{"NetworkMode":"default"}' 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .HostConfig.NetworkMode="host"

t DELETE containers/$cid?v=true 204

# test create container like Docker >= 25 cli: NetworkMode="default" but EndpointsConfig struct is explicitly set and netns="host"
t POST containers/create \
  Image=$IMAGE \
  HostConfig='{"NetworkMode":"default"}' \
  NetworkingConfig='{"EndpointsConfig":{"default":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"","NetworkID":"","EndpointID":"","Gateway":"","IPAddress":"","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DriverOpts":null,"DNSNames":null}}}' \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .HostConfig.NetworkMode="host"

t DELETE containers/$cid?v=true 204

# test creating a container fails with netns="hosts" on podman side but keep using the default network mode
# on docker CLI side and trying to use --ip 1.2.3.4 which is only valid for the bridge network mode (docker CLI
# will assume the default is the bridge mode, so it's valid from docker CLI point of view).
t POST containers/create \
  Image=$IMAGE \
  HostConfig='{"NetworkMode":"default"}' \
  NetworkingConfig='{"EndpointsConfig":{"default":{"IPAMConfig":null,"Links":null,"Aliases":null,"MacAddress":"","NetworkID":"","EndpointID":"","Gateway":"","IPAddress":"1.2.3.4","IPPrefixLen":0,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"DriverOpts":null,"DNSNames":null}}}' \
  500 \
    .cause="networks and static ip/mac address can only be used with Bridge mode networking"

# Restart with the default containers.conf for next tests.
stop_service
start_service

# Test Compat Create with healthcheck, check default values
t POST containers/create Image=$IMAGE Cmd='["top"]' Healthcheck='{"Test":["true"]}' 201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
  .Config.Healthcheck.Interval=30000000000 \
  .Config.Healthcheck.Timeout=30000000000 \
  .Config.Healthcheck.Retries=3

# compat api: Test for mount options support
# Sigh, JSON can't handle octal. 0755(octal) = 493(decimal)
payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch","TmpfsOptions":{"SizeBytes":1024,"Mode":493}}]}'
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
    .HostConfig.Tmpfs['"/mnt/scratch"']~.*size=1024.* \
    .HostConfig.Tmpfs['"/mnt/scratch"']~.*mode=755.*

t DELETE containers/$cid?v=true 204

# compat api: tmpfs without mount options
payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch"}]}'
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
    .HostConfig.Tmpfs['"/mnt/scratch"']~.*tmpcopyup.* \

t DELETE containers/$cid?v=true 204

# compat api: bind mount without mount options
payload='{"Mounts":[{"Type":"bind","Source":"/tmp","Target":"/mnt"}]}'
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
    .HostConfig.Binds[0]~/tmp:/mnt:.* \

t DELETE containers/$cid?v=true 204

# test apiv2 create/commit
t POST containers/create \
  Image=$IMAGE \
  Entrypoint='["echo"]' \
  Cmd='["param1","param2"]' \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")

# No such container
t POST "commit?container=nonesuch" 404

cparam="repo=newrepo&tag=v3&comment=abcd&author=eric"
cparam="$cparam&format=docker&changes=CMD%20/bin/bar%0aEXPOSE%209090"
t POST "commit?container=${cid:0:12}&$cparam" 201 \
  .Id~[0-9a-f]\\{64\\}
iid=$(jq -r '.Id' <<<"$output")
t GET images/$iid/json 200 \
  .RepoTags[0]=docker.io/library/newrepo:v3 \
  .Config.ExposedPorts~.*"9090/tcp" \
  .Config.Cmd~.*"/bin/bar" \
  .Comment="abcd"

t DELETE containers/$cid 204
t DELETE images/docker.io/library/newrepo:v3?force=false 200

# test create without default no_hosts
t POST containers/create \
  Image=$IMAGE \
  201 \
  .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")

t POST libpod/containers/$cid/init 204

t GET libpod/containers/$cid/json 200

cpid_file=$(jq -r '.ConmonPidFile' <<<"$output")
userdata_path=$(dirname $cpid_file)

t GET libpod/containers/$cid/json 200 \
  .HostsPath=$userdata_path/hosts

t DELETE containers/$cid 204

# test create with default no_hosts=true
stop_service

CONTAINERS_CONF=$TESTS_DIR/containers.no_hosts.conf start_service

# check docker and libpod endpoint
for endpoint in containers/create libpod/containers/create; do
  t POST $endpoint \
    Image=$IMAGE \
    201 \
    .Id~[0-9a-f]\\{64\\}
  cid=$(jq -r '.Id' <<<"$output")

  t POST libpod/containers/$cid/init 204

  t GET libpod/containers/$cid/json 200 \
    .HostsPath=""

  t DELETE containers/$cid 204
done

stop_service
start_service

# Our states are different from Docker's.
# Regression test for #14700 (Docker compat returning unknown "initialized" for status.status) to ensure the stay compatible
podman create --name status-test $IMAGE sh -c "sleep 3"
t GET containers/status-test/json 200 .State.Status="created"

podman init status-test
t GET containers/status-test/json 200 .State.Status="created"

podman start status-test
t GET containers/status-test/json 200 .State.Status="running"

podman pause status-test
t GET containers/status-test/json 200 .State.Status="paused"

podman unpause status-test
t GET containers/status-test/json 200 .State.Status="running"

podman stop status-test &
sleep 1
t GET containers/status-test/json 200 .State.Status="stopping"

sleep 3
t GET containers/status-test/json 200 .State.Status="exited"

# test podman generate spec as input for the api
cname=specgen$(random_string 10)
podman create --name=$cname $IMAGE

TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX)

podman generate spec -f ${TMPD}/myspec.json -c $cname

# Create a container based on that spec
t POST libpod/containers/create ${TMPD}/myspec.json 201 \
  .Id~[0-9a-f]\\{64\\}

# Verify
t GET libpod/containers/$cname/json 200 \
  .ImageName=$IMAGE \
  .Name=$cname

if root; then
  podman run -dt --name=updateCtr alpine
  echo '{"Memory":{"Limit":500000}, "CPU":{"Shares":123}}' >${TMPD}/update.json
  t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201

  cgroupPath=/sys/fs/cgroup/cpu.weight
  # 002 is the byte length
  cpu_weight_expect=$'\001\0025'

  # Verify
  echo '{ "AttachStdout":true,"Cmd":["cat", "'$cgroupPath'"]}' >${TMPD}/exec.json
  t POST containers/updateCtr/exec ${TMPD}/exec.json 201 .Id~[0-9a-f]\\{64\\}
  eid=$(jq -r '.Id' <<<"$output")
  t POST exec/$eid/start 200 $cpu_weight_expect

  # Now use the compat API
  echo '{ "Memory": 536870912 }' >${TMPD}/compatupdate.json
  t POST containers/updateCtr/update ${TMPD}/compatupdate.json 200
  t GET libpod/containers/updateCtr/json 200 \
    .HostConfig.Memory=536870912

  podman rm -f updateCtr
fi

rm -rf $TMPD

podman container rm -fa

# 18951: Make sure container create supports the platform parameter.  Force an
# initial architecture to make sure the test runs on all platforms.
podman pull --platform=linux/amd64 $IMAGE
t POST containers/create?platform=linux/amd64 \
  Image=$IMAGE \
  201
t POST containers/create?platform=linux/aarch64 \
  Image=$IMAGE \
  404
podman rmi -f $IMAGE
